package com.stylefeng.guns.rest.modular.auth.converter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.stylefeng.guns.core.exception.GunsException;
import com.stylefeng.guns.core.support.HttpKit;
import com.stylefeng.guns.core.util.MD5Util;
import com.stylefeng.guns.rest.common.exception.BizExceptionEnum;
import com.stylefeng.guns.rest.config.properties.JwtProperties;
import com.stylefeng.guns.rest.enums.WithSingEnums;
import com.stylefeng.guns.rest.enums.WithoutLoginEnums;
import com.stylefeng.guns.rest.modular.auth.security.DataSecurityAction;
import com.stylefeng.guns.rest.modular.auth.util.JwtTokenUtil;
import org.apache.catalina.connector.CoyoteInputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.nio.charset.Charset;

/**
 * 带签名的http信息转化器
 *
 * @author fengshuonan
 * @date 2017-08-25 15:42
 */
public class WithSignMessageConverter extends FastJsonHttpMessageConverter {

    @Autowired
    JwtProperties jwtProperties;

    @Autowired
    JwtTokenUtil jwtTokenUtil;

    @Autowired
    DataSecurityAction dataSecurityAction;

    private FastJsonConfig fastJsonConfig = new FastJsonConfig();
    protected Logger LOGGER = LoggerFactory.getLogger(getClass());

    @Override
    public Object read(Type type, Class<?> contextClass, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        if(HttpKit.getRequest().getServletPath().equals("/wz/pay/mobilePayNotify") || HttpKit.getRequest().getServletPath().equals("/wz/pay/wxpayNotify")){
            return this.readType(this.getType(type, contextClass), inputMessage);
        }
        String JWT = HttpKit.getRequest().getHeader("JWT");
        if(JWT == null){//兼容老版本
            LOGGER.debug("签名校验失败,用户版本是老版本!");
//            return this.readType(this.getType(type, contextClass), inputMessage);
            return  null;
        }else if(JWT.equals("wztest")){
            return this.readType(this.getType(type, contextClass), inputMessage);
        }else if(JWT.equals("true")){
            InputStream in = inputMessage.getBody();
            Object o = JSON.parseObject(in, super.getFastJsonConfig().getCharset(), BaseTransferEntity.class, super.getFastJsonConfig().getFeatures());
            //先转化成原始的对象
            BaseTransferEntity baseTransferEntity = (BaseTransferEntity) o;
            //校验签名
            String object = baseTransferEntity.getObject();
            String json = dataSecurityAction.unlock(object);
            //不需要验证接口
            for(WithSingEnums e: WithSingEnums.values()){
                String pass = HttpKit.getRequest().getServletPath().substring(0,17);
                if(pass.equals(e.getPath()) || HttpKit.getRequest().getServletPath().equals(e.getPath())){
                    //校验签名后再转化成应该的对象
                    return JSON.parseObject(json, type);
                }
            }
            //校验签名
            String token = HttpKit.getRequest().getHeader(jwtProperties.getHeader()).substring(7);
            String md5KeyFromToken = jwtTokenUtil.getMd5KeyFromToken(token);
            String encrypt = MD5Util.encrypt(object + md5KeyFromToken);
            if (!encrypt.equals(baseTransferEntity.getSign())) {
                LOGGER.debug("签名校验失败,数据被改动过!");
                throw new GunsException(BizExceptionEnum.SIGN_ERROR);
            }
            //校验签名后再转化成应该的对象
            return JSON.parseObject(json, type);
        }else{
            return null;
        }
    }

    private Object readType(Type type, HttpInputMessage inputMessage) throws IOException {
        try {
            InputStream in = inputMessage.getBody();
            return JSON.parseObject(in, this.fastJsonConfig.getCharset(), type, this.fastJsonConfig.getFeatures());
        } catch (JSONException var4) {
            throw new HttpMessageNotReadableException("JSON parse error: " + var4.getMessage(), var4);
        } catch (IOException var5) {
            throw new HttpMessageNotReadableException("I/O error while reading input message", var5);
        }
    }
}
